package doInterce.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.swing.clipboard.ClipboardUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import doInterce.DoInterface;
import utils.DBUtil;
import utils.ExceptionUtil;
import utils.YearUtil;
import utils.YmlUtil;

import javax.swing.*;
import java.awt.*;
import java.sql.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description: 查找没有生成的单位
 * @Author: syh
 * @Date: 2024/01/12/9:12
 */
public class DoFindNotGenerateUnit implements DoInterface {
    @Override
    public void doExecute() {
        Map<String, Object> ymlMap = YmlUtil.getYmlMap();
        String url = Convert.toStr(ymlMap.get("url"));
        String userName = Convert.toStr(ymlMap.get("userName"));
        String password = Convert.toStr(ymlMap.get("password"));

        start(DBUtil.getConnection(url,userName,password));

    }

    public void start(Connection conn) {


        // 创建一个 JFrame 实例
        JFrame frame = new JFrame("查找报表数量有差距的单位（工资）S");

        // 创建标签、输入框、下拉框、文本框和按钮
        JLabel yearLabel = new JLabel("年报年份:");

        Object[] yearArr = YearUtil.getYear();
        String[] yearOptions = (String[])yearArr[0];
        JComboBox<String> yearComboBox = getComboBox(yearOptions,300,30);
        if(yearArr[1] != null){
            String defaultYear = (String)yearArr[1];
            yearComboBox.setSelectedIndex(ArrayUtil.indexOf(yearOptions,defaultYear));
        }

        JLabel unitLabel = new JLabel("单位名称:");
        JTextField unitText = getInput(330,30);

        JLabel typeLabel = new JLabel("报表类型:");
        String[] typeOptions = {"公务员表" ,"参公群团表","参公事业表"};
        JComboBox<String> typeComboBox = getComboBox(typeOptions,300,30);

        JLabel nameLabel = new JLabel("报表名称:");
        String[] nameOptions = {"第一表   公务员工资情况（中央一级机关）（一）","第一表   公务员工资情况（中央一级机关）（二）","第二表   公务员工资情况（中央设在地方机关）（一）","第二表   公务员工资情况（中央设在地方机关）（二）","第三表   公务员工资情况（省、区、市一级机关）（一）","第三表   公务员工资情况（省、区、市一级机关）（二）","第四表   公务员工资情况（省、区、市设在地方机关）（一）","第四表   公务员工资情况（省、区、市设在地方机关）（二）","第五表   公务员工资情况（副省级市机关）（一）","第五表   公务员工资情况（副省级市机关）（二）","第六表   公务员工资情况（市、地、州、盟机关）（一）","第六表   公务员工资情况（市、地、州、盟机关）（二）","第七表   公务员工资情况（县、市、区、旗机关）（一）","第七表   公务员工资情况（县、市、区、旗机关）（二）","第八表   公务员工资情况（街道机关）（一）","第八表   公务员工资情况（街道机关）（二）","第九表   公务员工资情况（乡、镇机关）（一）","第九表   公务员工资情况（乡、镇机关）（二）","第十表   专业技术类职级（不含人民警察）工资情况","第十一表   法官助理、检察官助理和书记员工资情况","第十二表   国家综合消防救援队伍工资情况","第十三表   公务员级别工资档次分布情况（一）","第十三表   公务员级别工资档次分布情况（二）","第十三表   公务员级别工资档次分布情况（三）","第十四表   法官、检察官职务等级工资档次分布情况","第十五表   执法勤务职级、警务技术职级工资档次分布情况（一）","第十五表   执法勤务职级、警务技术职级工资档次分布情况（二）","第十五表   执法勤务职级、警务技术职级工资档次分布情况（三）","第十五表   执法勤务职级、警务技术职级工资档次分布情况（四）","第十六表   消防救援干部衔级工资档次分布情况","第十七表   公务员艰苦边远地区津贴分类区人数情况","第十八表   公务员工作年限情况（一）","第十八表   公务员工作年限情况（二）","第十九表   国家综合消防救援队伍工作年限情况","第二十表   公务员工资情况（总表）（一）","第二十表   公务员工资情况（总表）（二）","第二十一表   各层次机关公务员工资情况","第二十二表   参照管理群团机关工作人员工资情况","第二十三表   参照管理事业单位工作人员工资情况（总表）（一）","第二十三表   参照管理事业单位工作人员工资情况（总表）（二）","第二十四表   参照管理事业单位工作人员工资情况（中央一级）（一）","第二十四表   参照管理事业单位工作人员工资情况（中央一级）（二）","第二十五表   参照管理事业单位工作人员工资情况（中央设在地方）（一）","第二十五表   参照管理事业单位工作人员工资情况（中央设在地方）（二）","第二十六表   参照管理事业单位工作人员工资情况（地方）（一）","第二十六表   参照管理事业单位工作人员工资情况（地方）（二）","第二十七表   机关离休人员待遇情况（中央一级）","第二十八表   机关离休人员待遇情况（中央设在地方）","第二十九表   机关离休人员待遇情况（省、区、市）","第三十表   机关不同时期离休人员待遇情况","第三十一表   机关离休人员待遇情况（总表）"};
        JComboBox<String> nameComboBox = getComboBox(nameOptions,330,30);

        JLabel rowLabel = new JLabel("报表行数:");
        JTextField rowText = getInput(300,30);
        JLabel colLabel = new JLabel("报表列数:");
        JTextField colText = getInput(330,30);

        JLabel sqlLabel = new JLabel("反查语句:");
        JTextArea sqlArea = getTextArea(100, 20);

        JLabel outLabel = new JLabel("日志输出:");
        JTextArea outArea = getTextArea(690,50);
        JButton button = new JButton("开始执行");
        JButton clearBtn = new JButton("清空日志");
        JButton copyBtn = new JButton("复制所有日志");
        JButton copyUnitBtn = new JButton("复制有差距的单位");

        // 创建面板并添加组件
        JPanel panel = new JPanel();
        panel.add(yearLabel);
        panel.add(yearComboBox);

        panel.add(unitLabel);
        panel.add(unitText);

        panel.add(typeLabel);
        panel.add(typeComboBox);

        panel.add(nameLabel);
        panel.add(nameComboBox);

        panel.add(rowLabel);
        panel.add(rowText);

        panel.add(rowLabel);
        panel.add(rowText);

        panel.add(colLabel);
        panel.add(colText);

        panel.add(sqlLabel);

        JScrollPane scrollPane = new JScrollPane(sqlArea);
        panel.add(scrollPane);

        panel.add(outLabel);
        JScrollPane outAreaScrollPane = new JScrollPane(outArea);
        panel.add(outAreaScrollPane);

        panel.add(button);
        panel.add(clearBtn);
        panel.add(copyUnitBtn);
        panel.add(copyBtn);


        /**
         * 开始执行的点击事件
         */
        button.addActionListener(e -> {
            outArea.setText("");

            //收集页面数据
            QueryInfo queryInfo = new QueryInfo();
            queryInfo.setYear(yearComboBox.getSelectedItem()+"");
            queryInfo.setUnit(unitText.getText().trim());
            queryInfo.setType(typeComboBox.getSelectedItem()+"");
            queryInfo.setName(nameComboBox.getSelectedItem()+"");
            queryInfo.setRow(rowText.getText().trim());
            queryInfo.setCol(colText.getText().trim());
            queryInfo.setSql(sqlArea.getText().trim());

            outArea.append("开始信息校验\n");
            //校验数据
            try {
                String tip = verifyQueryInfo(queryInfo, conn);
                if(StrUtil.isNotEmpty(tip)){
                    outArea.append(tip+"\n");
                    JOptionPane.showMessageDialog(null, tip, "错误", JOptionPane.INFORMATION_MESSAGE);
                    return;
                }

                startFind(queryInfo, conn,outArea);
            }catch (Exception exception) {
                outArea.append("出现异常，程序已经终止！\n");
                JOptionPane.showMessageDialog(null, "校验过程出错！"+exception.getMessage(), "错误", JOptionPane.INFORMATION_MESSAGE);
                ExceptionUtil.writeLog(exception);

                return;
            }
            outArea.append("信息校验完成\n");

        });

        /**
         * 复制日志
         */
        clearBtn.addActionListener(e -> {
            outArea.setText("");
        });

        /**
         * 复制日志
         */
        copyBtn.addActionListener(e -> {
            String text = outArea.getText();
            ClipboardUtil.setStr(text);
        });

        /**
         * 复制单位按钮
         */
        copyUnitBtn.addActionListener(e -> {
            String text = outArea.getText();
            String[] logList = text.split("\n");
            String content = Arrays.stream(logList).filter(ele -> ele.startsWith("单位信息======  ")).collect(Collectors.joining("\n"));
            ClipboardUtil.setStr(content);
        });

        // 将面板添加到框架中
        frame.add(panel);

        // 设置框架属性
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    /**
     * 开始对比有差距的单位
     * @param queryInfo
     * @param conn
     * @param outArea
     * @throws SQLException
     */
    public void startFind(QueryInfo queryInfo, Connection conn,JTextArea outArea) throws SQLException {
        String reportTableName = "J"+queryInfo.getYear().substring(2)+"08";
        queryInfo.setCol("J"+queryInfo.getCol());

        Statement statement = conn.createStatement();
        ResultSet resultSet = statement.executeQuery("select id from tj_un where rptyear='" + queryInfo.getYear() + "' and name='" + queryInfo.getUnit() + "'");
        //机构编码
        String unitId = DBUtil.getStringValue(resultSet, null);
        resultSet.close();

        //查找所有的编码
        resultSet = statement.executeQuery("select id,name from tj_un where id like '" + unitId + "%' and rptyear='" + queryInfo.getYear() + "' and id in (select unid from M_S01 where  S0103='"+queryInfo.getType()+"' and rpt='2023') and id in (select TBUNITID from tb_set_unit where TBID='"+reportTableName+"') order by id");
        List<Map<String,String>> unitIdList = DBUtil.getFieldMapList(resultSet, resultSet.getMetaData());
        resultSet.close();

        outArea.append("开始查找数据，总共需要校核"+unitIdList.size()+"个单位\n");



        //查找所有报表数据
        Map<String,Double> reportUnitDataMap = new HashMap<>();
        String reportSql = "select unitid,"+queryInfo.getCol()+" from "+reportTableName+" where tableid='"+queryInfo.getName()+"' and unitid like '"+unitId+"%' and rowsid="+queryInfo.getRow()+"";
        outArea.append("报表查询语句："+reportSql+"\n");

        Statement reportStatement = conn.createStatement();
        ResultSet reportRs = reportStatement.executeQuery(reportSql);
        while (reportRs.next()){
            reportUnitDataMap.put(reportRs.getString(1),reportRs.getDouble(2));
        }
        reportRs.close();
        reportStatement.close();

        //开始各单位的反查
        String verifySql = queryInfo.getSql().replaceAll("M_S07.UNID[ ]+IN[ ]+\\('001\\.001[\\d\\.a-zA-Z]*'\\)", "M_S07.UNID like ? ");
        PreparedStatement verifyStatement = conn.prepareStatement(verifySql);
        outArea.append("转化后的反查语句："+verifySql+"\n");
        int index = 1;
        for(Map<String,String> tempUnitMap : unitIdList){
            verifyStatement.setString(1,tempUnitMap.get("ID")+"%");
            ResultSet tempRs = verifyStatement.executeQuery();
            double d = -1;
            if (tempRs.next()) {
                d = tempRs.getDouble(1);
            }
            Double reportValue = reportUnitDataMap.get(tempUnitMap.get("ID"));
            if (reportValue == null) {
                outArea.append("单位信息======  "+tempUnitMap.get("NAME")+" 报表：空"+"，"+"反查："+d+"\n");
            }else if(d != reportValue){
                outArea.append("单位信息======  "+tempUnitMap.get("NAME")+" 报表："+reportValue+"，"+"反查："+d+"\n");
            }

            outArea.append("已经完成"+index+"/"+unitIdList.size()+"个单位，当前单位为"+tempUnitMap.get("NAME")+"\n");
            index++;
        }

    }


    public static JTextField getInput(int width,int height) {
        JTextField textField = new JTextField(); // 10 是文本框的列数，可以调整文本框的宽度
        textField.setPreferredSize(new Dimension(width, height)); // 设置文本框的宽度和高度

        return textField;
    }

    public static JComboBox getComboBox(String[] typeOptions,int width,int height) {
        JComboBox<String> comboBox = new JComboBox<>(typeOptions);
        comboBox.setPreferredSize(new Dimension(width, height));
        return comboBox;
    }

    public static JTextArea getTextArea(int width,int height) {
        JTextArea textArea = new JTextArea(10, 63);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        return textArea;
    }


    /**
     * 验证填写的信息是否正确
     * @param queryInfo
     * @return
     */
    public String verifyQueryInfo(QueryInfo queryInfo,Connection conn) throws SQLException {
        if(StrUtil.isBlank(queryInfo.getYear()) || "null".equals(queryInfo.getYear())){
            return "年份没有填写!";
        }
        if(StrUtil.isBlank(queryInfo.getUnit())){
            return "单位名称没有填写!";
        }
        if(StrUtil.isBlank(queryInfo.getType()) || "null".equals(queryInfo.getType())){
            return "查询类型没有填写!";
        }
        if(StrUtil.isBlank(queryInfo.getName()) || "null".equals(queryInfo.getName())){
            return "报表名称没有填写!";
        }
        if(StrUtil.isBlank(queryInfo.getRow())){
            return "行数没有填写!";
        }
        if(StrUtil.isBlank(queryInfo.getCol())){
            return "列数没有填写!";
        }
        if(StrUtil.isBlank(queryInfo.getSql())){
            return "反查语句没有填写!";
        }

        Statement statement = conn.createStatement();
        ResultSet resultSet = statement.executeQuery("select count(1) cut from tj_un where rptyear='" + queryInfo.getYear() + "' and name='" + queryInfo.getUnit() + "'");
        if(resultSet.next()){
            if(resultSet.getInt(1) == 0){
                return "没有找到该单位，请检查是否填写和系统的一致!";
            }
            if(resultSet.getInt(1) > 1){
                return "系统有多个重名的单位，无法继续查询!";
            }
        }
        resultSet.close();
        statement.close();

        String typeCode = getTypeCode(queryInfo.getType());
        queryInfo.setType(typeCode);
        if(StrUtil.isBlank(typeCode)){
            return "没有找到该报表类型!";
        }

        String tableId = getTableId(queryInfo.getName());
        if(StrUtil.isBlank(tableId)){
            return "没有找到该报表!";
        }
        queryInfo.setName(tableId); //替换成编码

        if(!queryInfo.getRow().matches("\\d+")){
            return "行数不是数字!";
        }
        if(!queryInfo.getCol().matches("\\d+")){
            return "列数不是数字!";
        }

        Pattern pattern = Pattern.compile("M_S07.UNID[ ]+IN[ ]+\\('001\\.001[\\d\\.a-zA-Z]*'\\)");
        Matcher matcher = pattern.matcher(queryInfo.getSql());
        if(!matcher.find()){
            return "反查语句中没有包含M_S07.UNID IN ('机构编码')!";
        }

        return null;
    }


    /**
     * 查找报表类型编码
     * @param name
     * @return
     */
    public String getTypeCode(String name){
        Map<String,String> nameMap = new HashMap<>();
        nameMap.put("公务员表","1");
        nameMap.put("参公事业表","3");
        nameMap.put("参公群团表","2");

        return nameMap.get(name);
    }
    /**
     * 根据名称来查找表id
     * @param tableName
     * @return
     */
    public static String getTableId(String tableName){
        Map<String,String> nameMap = new HashMap<>();
        nameMap.put("第一表   公务员工资情况（中央一级机关）（一）","J2308001");
        nameMap.put("第一表   公务员工资情况（中央一级机关）（二）","J2308002");
        nameMap.put("第二表   公务员工资情况（中央设在地方机关）（一）","J2308003");
        nameMap.put("第二表   公务员工资情况（中央设在地方机关）（二）","J2308004");
        nameMap.put("第三表   公务员工资情况（省、区、市一级机关）（一）","J2308005");
        nameMap.put("第三表   公务员工资情况（省、区、市一级机关）（二）","J2308006");
        nameMap.put("第四表   公务员工资情况（省、区、市设在地方机关）（一）","J2308007");
        nameMap.put("第四表   公务员工资情况（省、区、市设在地方机关）（二）","J2308008");
        nameMap.put("第五表   公务员工资情况（副省级市机关）（一）","J2308009");
        nameMap.put("第五表   公务员工资情况（副省级市机关）（二）","J2308010");
        nameMap.put("第六表   公务员工资情况（市、地、州、盟机关）（一）","J2308011");
        nameMap.put("第六表   公务员工资情况（市、地、州、盟机关）（二）","J2308012");
        nameMap.put("第七表   公务员工资情况（县、市、区、旗机关）（一）","J2308013");
        nameMap.put("第七表   公务员工资情况（县、市、区、旗机关）（二）","J2308014");
        nameMap.put("第八表   公务员工资情况（街道机关）（一）","J2308015");
        nameMap.put("第八表   公务员工资情况（街道机关）（二）","J2308016");
        nameMap.put("第九表   公务员工资情况（乡、镇机关）（一）","J2308017");
        nameMap.put("第九表   公务员工资情况（乡、镇机关）（二）","J2308018");
        nameMap.put("第十表   专业技术类职级（不含人民警察）工资情况","J2308052");
        nameMap.put("第十一表   法官助理、检察官助理和书记员工资情况","J2308053");
        nameMap.put("第十二表   国家综合消防救援队伍工资情况","J2308020");
        nameMap.put("第十三表   公务员级别工资档次分布情况（一）","J2308021");
        nameMap.put("第十三表   公务员级别工资档次分布情况（二）","J2308022");
        nameMap.put("第十三表   公务员级别工资档次分布情况（三）","J2308023");
        nameMap.put("第十四表   法官、检察官职务等级工资档次分布情况","J2308024");
        nameMap.put("第十五表   执法勤务职级、警务技术职级工资档次分布情况（一）","J2308025");
        nameMap.put("第十五表   执法勤务职级、警务技术职级工资档次分布情况（二）","J2308026");
        nameMap.put("第十五表   执法勤务职级、警务技术职级工资档次分布情况（三）","J2308027");
        nameMap.put("第十五表   执法勤务职级、警务技术职级工资档次分布情况（四）","J2308028");
        nameMap.put("第十六表   消防救援干部衔级工资档次分布情况","J2308029");
        nameMap.put("第十七表   公务员艰苦边远地区津贴分类区人数情况","J2308030");
        nameMap.put("第十八表   公务员工作年限情况（一）","J2308031");
        nameMap.put("第十八表   公务员工作年限情况（二）","J2308032");
        nameMap.put("第十九表   国家综合消防救援队伍工作年限情况","J2308034");
        nameMap.put("第二十表   公务员工资情况（总表）（一）","J2308035");
        nameMap.put("第二十表   公务员工资情况（总表）（二）","J2308036");
        nameMap.put("第二十一表   各层次机关公务员工资情况","J2308037");
        nameMap.put("第二十二表   参照管理群团机关工作人员工资情况","J2308038");
        nameMap.put("第二十三表   参照管理事业单位工作人员工资情况（总表）（一）","J2308039");
        nameMap.put("第二十三表   参照管理事业单位工作人员工资情况（总表）（二）","J2308040");
        nameMap.put("第二十四表   参照管理事业单位工作人员工资情况（中央一级）（一）","J2308046");
        nameMap.put("第二十四表   参照管理事业单位工作人员工资情况（中央一级）（二）","J2308047");
        nameMap.put("第二十五表   参照管理事业单位工作人员工资情况（中央设在地方）（一）","J2308048");
        nameMap.put("第二十五表   参照管理事业单位工作人员工资情况（中央设在地方）（二）","J2308049");
        nameMap.put("第二十六表   参照管理事业单位工作人员工资情况（地方）（一）","J2308050");
        nameMap.put("第二十六表   参照管理事业单位工作人员工资情况（地方）（二）","J2308051");
        nameMap.put("第二十七表   机关离休人员待遇情况（中央一级）","J2308041");
        nameMap.put("第二十八表   机关离休人员待遇情况（中央设在地方）","J2308042");
        nameMap.put("第二十九表   机关离休人员待遇情况（省、区、市）","J2308043");
        nameMap.put("第三十表   机关不同时期离休人员待遇情况","J2308044");
        nameMap.put("第三十一表   机关离休人员待遇情况（总表）","J2308045");

        return nameMap.get(tableName);
    }


    /**
     * 查询信息
     */
    class QueryInfo{
        private String year;
        private String unit;
        private String type;
        private String name;
        private String row;
        private String col;
        private String sql;
        private String output;


        public QueryInfo(String year, String unit, String type, String name, String row, String col, String sql, String output) {
            this.year = year;
            this.unit = unit;
            this.type = type;
            this.name = name;
            this.row = row;
            this.col = col;
            this.sql = sql;
            this.output = output;
        }

        public String getYear() {
            return year;
        }

        public void setYear(String year) {
            this.year = year;
        }

        public String getUnit() {
            return unit;
        }

        public void setUnit(String unit) {
            this.unit = unit;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getRow() {
            return row;
        }

        public void setRow(String row) {
            this.row = row;
        }

        public String getCol() {
            return col;
        }

        public void setCol(String col) {
            this.col = col;
        }

        public String getSql() {
            return sql;
        }

        public void setSql(String sql) {
            this.sql = sql;
        }

        public String getOutput() {
            return output;
        }

        public void setOutput(String output) {
            this.output = output;
        }

        public QueryInfo() {
        }
    }



}
